package com.example.securityproject.demos.controller;

import com.alibaba.fastjson.JSONObject;
import com.example.securityproject.demos.anotation.Anonymous;
import com.example.securityproject.demos.common.CommonResult;
import com.example.securityproject.demos.entity.TUser;
import com.example.securityproject.demos.entity.User;
import com.example.securityproject.demos.service.TUserService;
import com.example.securityproject.demos.utils.JwtUtils;
import com.example.securityproject.demos.dto.LoginDTO;
import com.example.securityproject.demos.utils.RedisUtils;
import com.example.securityproject.demos.vo.MenuVO;
import com.example.securityproject.demos.dto.RegisterDTO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @BelongsProject: springBootProject
 * @BelongsPackage: com.example.springbootproject.controller
 * @Author: Jiangjb
 * @CreateTime: 2022-06-08  15:51
 * @Description: TODO
 * @Version: 1.0
 */
@RestController
@RequestMapping("/test")
@Slf4j
public class HelloWorldController {

    private static final String USER_PREFIX = "login:";

    private final AuthenticationManager authenticationManager;

//    @Autowired
//    private RedisTemplate redisTemplate;

    @Autowired
    private RedisUtils redisUtils;

    @Resource
    private TUserService tUserService;

    public HelloWorldController(AuthenticationManager authenticationManager) {
        this.authenticationManager = authenticationManager;
    }

    @PostMapping("/login")
    @Anonymous
    public CommonResult login(@RequestBody LoginDTO userLogin) throws AuthenticationException {
        //通过AuthenticationManager的authenticate方法来进行用户认证
        UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(userLogin.getUsername(), userLogin.getPassword());
        Authentication authenticate = authenticationManager.authenticate(usernamePasswordAuthenticationToken);
        if (authenticate == null) {
            return CommonResult.error(401, "登录校验失败");
        } else {
            //获取用户信息
            User user = (User) authenticate.getPrincipal();
            //获取用户id
            Integer id = user.getLoginUser().getId();
            String username = user.getLoginUser().getUsername();
            List<GrantedAuthority> authorities = new ArrayList<>();
            if (!StringUtils.isEmpty(username)) {
                List<MenuVO> menus = tUserService.queryMenus(username);
                for (MenuVO vo : menus) {
                    // 用户可以访问的资源名称（或者说用户所拥有的权限） 注意：必须"ROLE_"开头
                    authorities.add(new SimpleGrantedAuthority("ROLE_" + vo.getRoleName()));
                }
            }
            Map<String, Object> claims = new HashMap<>();
            claims.put("userId", id);
            claims.put("userName", username);
            claims.put("authorities", JSONObject.toJSONString(authorities));
            //根据用户id生成token
            String token = JwtUtils.createToken(claims);
            //将token放在redis中
            redisUtils.set(USER_PREFIX + String.valueOf(id), user, 30 * 60);
//            redisTemplate.opsForValue().set(USER_PREFIX + String.valueOf(id), user, 30, TimeUnit.MINUTES);
            return CommonResult.success(token);
        }
    }

    @PostMapping("/register")
    @Anonymous
    public CommonResult register(@RequestBody RegisterDTO dto) throws AuthenticationException {
        TUser tUser = new TUser(dto.getUsername(), dto.getUsername());
        boolean flag = tUserService.save(tUser);
        if (flag) {
            return CommonResult.success();
        }
        return CommonResult.error();
    }

    @PostMapping("/logout")
    @Anonymous
    public CommonResult logout() {
        //获取SecirityContextHolder中的用户id
        UsernamePasswordAuthenticationToken authenticate =
                (UsernamePasswordAuthenticationToken) SecurityContextHolder.getContext().getAuthentication();
        User user = (User) authenticate.getPrincipal();
        Integer id = user.getLoginUser().getId();
        //删除redis中的值
        redisUtils.del(USER_PREFIX + id);
        return CommonResult.success();
    }

    @Anonymous
    @GetMapping("/helloworld")
//    @PreAuthorize("hasRole('ROLE_USER')")
    public String hello() {
        return "hello world";
    }

    @PostMapping("/helloworld2")
    @PreAuthorize("hasRole('ROLE_ADMIN')")
    public String hello2(@RequestBody List<String> names) {
        return "hello world！" + String.join(",", names);
    }

    @PostMapping("/helloworld3")
    @PreAuthorize("hasRole('ROLE_USER') and hasRole('ROLE_ADMIN')")
    public String hello3(@RequestParam("names") List<String> names) {
        return "hello world！" + String.join(",", names);
    }
}
